package com.only4play.user.service.imlp;

import com.only4play.common.PasswordGenerator;
import com.only4play.idgenerator.provider.IdGenerator;
import com.only4play.user.model.dto.input.PersonManagerRegisterRequestDto;
import com.only4play.user.model.dto.input.PersonResetPasswordRequestDto;
import com.only4play.user.model.dto.input.PersonUpdateRequestDto;
import com.only4play.user.model.dto.output.PersonRegisterResponseDto;
import com.only4play.user.utils.converter.UserPersonConverter;
import com.only4play.user.model.dto.input.PersonRegisterRequestDto;
import com.only4play.user.model.dto.output.UserPersonalAccountDto;
import com.only4play.user.model.entity.UserPersonalAccount;
import com.only4play.user.repository.UserPersonalAccountRepository;
import com.only4play.user.repository.UserPersonRepository;
import com.only4play.user.service.UserPersonalAccountService;
import com.only4play.auth.AuthenticatedUser;
import com.only4play.common.model.entity.RowStatus;
import com.only4play.user.model.entity.UserPerson;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;


/**
 * @author liyuncong
 * @version 1.0
 * @file UserPersonalAccountServiceImpl.java
 * @brief UserPersonalAccountServiceImpl
 * @details UserPersonalAccountServiceImpl
 * @date 2022-04-01
 * <p>
 * Edit History
 * ----------------------------------------------------------------------------
 * DATE                        NAME               DESCRIPTION
 * 2022-04-01                  liyuncong          Created
 */
@Log4j2
@Service
public class UserPersonalAccountServiceImpl implements UserPersonalAccountService {

    @Autowired
    @Qualifier("passwordEncoder")
    private PasswordEncoder passwordEncoder;
    @Autowired
    private PasswordGenerator passwordGenerator;
    @Autowired
    private UserPersonRepository personRepository;
    //    @Autowired
    private final UserPersonConverter personConverter = new UserPersonConverter();
    @Autowired
    private UserPersonalAccountRepository accountRepository;
    @Autowired
    private IdGenerator idGenerator;

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Optional<PersonRegisterResponseDto> register(PersonRegisterRequestDto requestDto) {
        UserPerson userinfo = UserPersonConverter.fromRegisterDto(requestDto);
        userinfo.setId(idGenerator.newString());
        UserPerson saveUser = personRepository.saveAndFlush(userinfo);
        UserPersonalAccount account = UserPersonConverter.fromRegisterDto(requestDto, passwordEncoder, passwordGenerator);
        account.setId(idGenerator.newString());
        account.setPerson(saveUser);
        UserPersonalAccount saveAccount = accountRepository.saveAndFlush(account);
        return Optional.of(UserPersonConverter.toRegisterResult(saveUser, saveAccount));
    }

    @Override
    public Optional<PersonRegisterResponseDto> managerCreatePerson(
        PersonManagerRegisterRequestDto requestDto
    ) {
        return Optional.empty();
    }

    @Override
    public Optional<UserPersonalAccountDto> authenticate(
        String username, String password
    ) {
        Optional<UserPersonalAccount> result =
            accountRepository.findByUsernameAndRowStatus(username, RowStatus.OK);
        if (result.isEmpty()) {
            return Optional.empty();
        }
        UserPersonalAccount account = result.get();
        boolean verify = passwordGenerator.verify(username, password, account.getPasswordSalt(), account.getPassword(), passwordEncoder);
        if (!verify) {
            return Optional.empty();
        }
        return result.map(personConverter::fromEntity);
    }

    @Override
    public Optional<UserPersonalAccountDto> getCurrentLoginPersonInfo() {
        Optional<AuthenticatedUser<?>> result = AuthenticatedUser.currentUser();
        return result
            .map(item -> personConverter.fromEntity(
                accountRepository.getReferenceById(item.getUserId())
            ));
    }

    @Override
    public Optional<UserPersonalAccountDto> updateAccountStatus(
        String userPersonalAccountId, Integer status) {
        return Optional.empty();
    }

    @Override
    public Optional<UserPersonalAccountDto> resetPassword(
        PersonResetPasswordRequestDto requestDto) {
        return Optional.empty();
    }

    @Override
    public Optional<UserPersonalAccountDto> updatePersonInfo(PersonUpdateRequestDto requestDto) {
        return Optional.empty();
    }

    @Override
    public Optional<UserPersonalAccountDto> queryPersonInfoByUsername(String username) {
        Optional<UserPersonalAccount> result =
            accountRepository.findByUsernameAndRowStatus(username, RowStatus.OK);
        return result.map(personConverter::fromEntity);
    }

    //    @Override
//    public IPage<UserPersonalAccountDto> searchUserPersonalAccounts(
//        Long userPersonalAccountId, PageableRequest pageRequest, String keyword
//    ) {
////        final int current = pageRequest.getPageIndex();
////        final int size = pageRequest.getPageSize();
////        final String sort = pageRequest.getOrder();
////        IPage<UserPersonalAccount> page = Page.of(current, size);
////        IPage<UserPersonalAccount> result = accountMapper.findAll(page, sort, keyword);
////        log.info(result);
////        return result.convert(item -> personConverter.fromEntity(item));
//        return new Page<>();
//    }
}
